/**
 * 
 */
package smallChanges.statements;

import java.util.List;

import smallChanges.Tokenization.TokenSet;

/**
 * A single statement.  This can be something literally a single statement, like x=5; 
 * or can be the header to a loop, class or method.
 * @author jspacco
 *
 */
public class SingleStatement extends Statement
{
    public static final SingleStatement NullStatement = new SingleStatement(0L,-1,-1,-1,-1) {
        public String toString() {
            return "";
        }
    };
    
	public SingleStatement(Long statementID, int beginLine, int beginColumn, int endLine, int endColumn)
	{
		super(null);
		setStatementID(statementID);
		this.beginColumn = beginColumn;
		this.beginLine = beginLine;
		this.endColumn = endColumn;
		this.endLine = endLine;
	}

	public SingleStatement(TokenSet tokenSet) {
        super(SINGLE_STATEMENT, tokenSet);
    }
    
    protected SingleStatement(String stmtType, TokenSet tokenSet) {
        super(stmtType, tokenSet);
    }
    
    /**
     * Necessary for Hibernate; shouldn't be called by anyone else!
     * XXX This is why a separate flat-statement is better than 
     * using SingleStatement.  We're putting a lot of stuff into this
     * class, and it's a base class for a lot of the things below it.
     */
    public SingleStatement() {}
    
    /**
     * copy-constructor
     * XXX Allows quasi-upcasts where we take leaf nodes
     * such as MethodSignature or ForLoopHeader
     * and "flatten" them into a SingleStatement in order
     * to put them into the "flat" STMT_Statements table in the DB.
     * This is a fairly ugly solution but right now is necessary
     * because we don't have the time to put the entire
     * structure of the Statement class hierarchy into the DB.
     * 
     * @param s The statement to be "upcast" to a SingleStatement
     * @para
     * @throws UnsupportedOperationException if the parameter s is 
     * not an instanceof SingleStatement.
     */
    public SingleStatement(Statement s) {
        if (!(s instanceof SingleStatement)) {
            throw new UnsupportedOperationException("Can only perform " +
            		"pseudo-upcast of SingleStatement sub-types");
        }
        StatementUtilities.copyCodeRange(s, this);
        setFileID(s.getFileID());
        setTransID(s.getTransID());
        setParentID(s.getParentID());
        // storing the statement's type in the DB
        // someday we should be able to use this to reconstruct the full
        // statement structure by looking up meta-information
        setStmtType(s.getStmtType());
        // copy over the tokens that are in range
        tokensInRange=s.getTokensInRange();
        // copy meta-info
        addAllMetaInfo(s.getMetaInformationAnnotations());
    }

    
    
    
    
    /**
     * Loads tokens included in the range of this statement from a given
     * TokenSet.  It's more efficient to load all of the tokens
     * that are in a file once and then use that to fill
     * all the statements.
     * @param tokenSet
     */
    public void loadTokens(TokenSet tokenSet)
    {
        allTokensInClass=tokenSet;
        setTokensFromRange();
    }
    
    
    
   
    
    

    
    /**
     * Helper method that converts a statement into a String, but takes into
     * account the nesting depth.
     * @param depth
     * @return
     */
    String toStringHelper(int depth)
    {
        return makePadding(depth)+getImage()+" => " +getCoords();
    }

    @Override
    List<Statement> flattenHelper(List<Statement> list)
    {
        list.add(this);
        return list;
    }

    @Override
    public String getImage()
    {
        return getTokenImage();
    }
}
